﻿namespace Guia.Elements
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Windows.Automation;
    using Guia.Config;
    using Guia.Core;
    using Guia.Locator;

    /// <summary>
    /// This class represents a Window.
    /// </summary>
    public class Window : UiElement, IWindow
    {
        /// <summary>
        /// Initializes a new instance of the Window class. 
        /// </summary>
        /// <param name="automationElement">The AutomationElement representating this Window.</param>
        public Window(AutomationElement automationElement)
            : base(automationElement)
        {
        }

        /// <summary>
        /// Gets the default-condition to find a control by its type.
        /// </summary>
        public static SearchCondition ControlTypeCondition
        {
            get { return SearchCondition.ByControlType(ControlType.Window); }
        }

        /// <summary>
        /// Gets the open MessageBox instance with the given name as title.
        /// </summary>
        /// <param name="name">The name of the MessageBox.</param>
        /// <returns>The MessageBox with the given title.</returns>
        /// <exception cref="ArgumentNullException">This exception is thrown if name is null.</exception>
        public MessageBox GetMessageBox(string name)
        {
            return this.Get<MessageBox>(SearchCondition.ByName(name));
        }

        /// <summary>
        /// Gets the SaveFileDialog instance of this window with the given name as title.
        /// </summary>
        /// <param name="name">The name of the SaveFileDialog.</param>
        /// <returns>The SaveFileDialog with the given title.</returns>
        /// <exception cref="ArgumentNullException">This exception is thrown if name is null.</exception>
        public SaveFileDialog GetSaveFileDialog(string name)
        {
            return this.Get<SaveFileDialog>(SearchCondition.ByName(name));
        }

        /// <summary>
        /// Gets the SaveFileDialog of this window with the default-title.
        /// </summary>
        /// <returns>The default-titled SaveFileDialog.</returns>
        public SaveFileDialog GetSaveFileDialog()
        {
            return this.GetSaveFileDialog(AppConfigImpl.Instance.GetLocalizedName(EElementIdentifier.SAVE_FILE_DEFAULT_TITLE));
        }

        /// <summary>
        /// Gets the OpenFileDialog instance of this window with the given name as title.
        /// </summary>
        /// <param name="name">The name of the OpenFileDialog.</param>
        /// <returns>The OpenFileDialog with the given title.</returns>
        /// <exception cref="ArgumentNullException">This exception is thrown if name is null.</exception>
        public OpenFileDialog GetOpenFileDialog(string name)
        {
            return this.Get<OpenFileDialog>(SearchCondition.ByName(name));
        }

        /// <summary>
        /// Gets the OpenFileDialog of this window with the default-title.
        /// </summary>
        /// <returns>The default-titled OpenFileDialog.</returns>
        public OpenFileDialog GetOpenFileDialog()
        {
            return this.GetOpenFileDialog(AppConfigImpl.Instance.GetLocalizedName(EElementIdentifier.OPEN_FILE_DEFAULT_TITLE));
        }

        /// <summary>
        /// Maximizes the window.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">If maximizing is not supported in the current context.</exception> 
        public void Maximize()
        {
            WindowPattern windowPattern = GetPattern<WindowPattern>();
            if (windowPattern.Current.CanMaximize)
            {
                windowPattern.SetWindowVisualState(WindowVisualState.Maximized);
            }
            else
            {
                throw new OperationNotSupportedException(
                    "Maximizing is not allowed for the window with the automation-id " + AutomationId);
            }
        }

        /// <summary>
        /// Closes the window.
        /// Attention: After closing the window, the behaviour of further operations depend on the actual execution-mode (Application or WindowControl / CustomControl). This is due to the fact that the closing-event of an application-window forces the dispatcher to shutdown. Whereas the closing-event in WindowControl / CustomControl mode does not force the dispatcher to shutdown (this is done by the Stop-method of the RunnableUiElement), thus operations after close-event may throw arbitary exceptions. 
        /// </summary>
        public void Close()
        {
            WindowPattern windowPattern = GetPattern<WindowPattern>();
            windowPattern.Close();
        }

        /// <summary>
        /// Minimizes the window.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">If minimizing is not supported in the current context.</exception> 
        public void Minimize()
        {
            WindowPattern windowPattern = GetPattern<WindowPattern>();
            if (windowPattern.Current.CanMinimize)
            {
                windowPattern.SetWindowVisualState(WindowVisualState.Minimized);
            }
            else
            {
                throw new OperationNotSupportedException("Minimizing is not allowed for the window with the automation-id " + AutomationId);
            }
        }

        /// <summary>
        /// Recovers the normal window-size. 
        /// </summary>
        public void RecoverNormal()
        {
            WindowPattern windowPattern = GetPattern<WindowPattern>();
            windowPattern.SetWindowVisualState(WindowVisualState.Normal);
        }

        /// <summary>
        /// Get the window's visual state.
        /// </summary>
        /// <returns>The current visual state of the window</returns>
        public WindowVisualState GetVisualState()
        {
            WindowPattern windowPattern = GetPattern<WindowPattern>();
            return windowPattern.Current.WindowVisualState;
        }

        /// <summary>
        /// Get the menu with the given automationId.
        /// </summary>
        /// <param name="automationId">The automationId of the desired Menu</param>
        /// <returns>A Menu instance.</returns>
        /// <exception cref="ArgumentNullException">This exception is thrown if automationId is null.</exception>
        public Menu GetMenu(string automationId)
        {
            return Get<Menu>(automationId);
        }
    }
}
